/*
 * Copyright 2006 Matt Jensen
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.spectaql.internal.metadata;

import org.spectaql.internal.util.CollectionUtils;
import org.spectaql.internal.util.Extractor;
import org.spectaql.metadata.EntityMetadata;
import org.spectaql.metadata.PropertyMetadata;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 * <code>EntityMetadataImpl</code> is the default implementation of the {@link EntityMetadata} interface.
 * </p>
 */
class EntityMetadataImpl implements EntityMetadata
{
    /**
     * <p>
     * The entity class.
     * </p>
     */
    private final Class<?> m_entityClass;

    /**
     * <p>
     * The entity name.
     * </p>
     */
    private final String m_entityName;

    /**
     * <p>
     * The identifier class. 
     * </p>
     */
    private final Class<?> m_identifierClass;

    /**
     * <p>
     * The property metadata map.
     * </p>
     */
    private final Map<String, PropertyMetadata> m_propertyMetadata;

    /**
     * <p>
     * Construct a {@link EntityMetadata} instance.
     * </p>
     *
     * @param entityName the entity name.
     * @param entityClass the entity class.
     * @param identifierClass the identifier class.
     * @param propertyMetadata the property metadata.
     */
    public EntityMetadataImpl(final String entityName,
                              final Class<?> entityClass,
                              final Class<?> identifierClass,
                              final Set<PropertyMetadata> propertyMetadata)
    {
        super();
        assert null != entityClass : "The [entityClass] argument cannot be null.";
        assert null != entityName : "The [entityName] argument cannot be null.";
        assert null != identifierClass : "The [identifierClass] argument cannot be null.";
        assert null != propertyMetadata : "The [propertyMetadata] argument cannot be null.";

        m_entityClass = entityClass;
        m_entityName = entityName;
        m_identifierClass = identifierClass;
        m_propertyMetadata = CollectionUtils.toMap(propertyMetadata, new Extractor<String, PropertyMetadata>()
        {
            public String extract(final PropertyMetadata object)
            {
                return object.getName();
            }
        });
    }

    /* inherit javadoc */
    public Class<?> getEntityClass()
    {
        return m_entityClass;
    }

    /* inherit javadoc */
    public String getEntityName()
    {
        return m_entityName;
    }

    /* inherit javadoc */
    public Class<?> getIdentifierClass()
    {
        return m_identifierClass;
    }

    /* inherit javadoc */
    public Collection<PropertyMetadata> getProperties()
    {
        return m_propertyMetadata.values();
    }

    /* inherit javadoc */
    public Iterator<String> getPropertyNames()
    {
        return m_propertyMetadata.keySet().iterator();
    }

    /* inherit javadoc */
    public PropertyMetadata getProperty(final String name) throws IllegalArgumentException
    {
        if (!m_propertyMetadata.containsKey(name))
        {
            throw new IllegalArgumentException("Property [" + name + "] does not exist on entity [" + m_entityName +
                    "].");
        }
        return m_propertyMetadata.get(name);
    }
}
